﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization.Formatters.Binary;
using PetkaWebDav.Server.Framework.BaseClasses;
using PetkaWebDav.Server.Framework.Classes;
using Microsoft.WindowsAzure.Storage.Blob;
using System.IO;
using PetkaWebDav.Server.Framework.Enums;

namespace PetkaWebDav.Handler.AzureBlob.Handlers
{
    /// <summary>
    /// Custom implementation example for DavLock.
    /// </summary>
    public sealed class DavLock : DavLockBase
    {
        public DavLock()
        {
            this.ProcessDavRequest += new DavProcessEventHandler(DavLock_ProcessDavRequest);
            this.RefreshLockDavRequest += new DavRefreshLockEventHandler(DavLock_RefreshLockDavRequest);
        }

        private void DavLock_ProcessDavRequest(object sender, EventArgs e)
        {

            //Check to see if the original resource exists
            CloudBlockBlob _fileInfo = RequestWrapper.DownloadBlobAttributes(base.RelativeRequestPath);
            if (_fileInfo == null)
                base.AbortRequest(ServerResponseCode.NotFound);
            else
            {
                //Check to see if a lock already exists
                CloudBlockBlob lockFile = RequestWrapper.GetLockFileByFileName(_fileInfo.Name);

                if (lockFile.Exists())
                    base.AbortRequest(DavLockResponseCode.Locked);
                else
                {
                    string _opaqueLock = System.Guid.NewGuid().ToString("D");

                    //Apply the requested lock information
                    base.ResponseLock.AddLockToken(_opaqueLock);

                    //Create the *.locked file
                    //RequestWrapper.GetLockInfo(_fileInfo.Name)
                    string _lockedFilePath = _fileInfo.Name + "." + _opaqueLock + ".locked";

                    using (MemoryStream _lockFileStream = new MemoryStream())
                    {
                        BinaryFormatter _binaryFormatter = new BinaryFormatter();
                        _binaryFormatter.Serialize(_lockFileStream, base.ResponseLock);
                        _lockFileStream.Position = 0;
                        RequestWrapper.UploadBlob(_lockedFilePath, _lockFileStream);
                    }
                }
            }
        }

        private void DavLock_RefreshLockDavRequest(object sender, DavRefreshEventArgs e)
        {
            //Check to see if the lock exists
            CloudBlockBlob _lockFile = RequestWrapper.GetLockFileByLockToken(e.LockToken);

            //if (_lockFiles.Length == 0)
            if (_lockFile == null)
                base.AbortRequest(DavLockResponseCode.PreconditionFailed);
            else
            {
                //Deserialize the lock information
                DavLockProperty _lockProperty = null;
                using (MemoryStream _lockFileStream = new MemoryStream())
                {
                    _lockFileStream.Position = 0;
                    BinaryFormatter _binaryFormatter = new BinaryFormatter();
                    _lockProperty = (DavLockProperty)_binaryFormatter.Deserialize(_lockFileStream);
                    _lockFileStream.Close();
                }

                base.ResponseLock = _lockProperty;

                //Set the requested lockTimeout or overwrite
                base.ResponseLock.LockTimeout = 10;
            }
        }
    }
}
